// Functions associated with the Sidebar class
//-----------------

//-----------------
// Includes libraries and other files
#include "Sidebar.h"
//-----------------

//-----------------
//// CONSTRUCTOR - Sidebar
Sidebar::Sidebar( const Window& window, UserInterface* p_ui, const int& height, const int& side)
	: p_ui_( p_ui), alignment_( side), button_active_( 0), button_mouseover_( -1), asset_mouseover_( 0), BUTTON_WIDTH( 150), BUTTON_HEIGHT( 30),
	  MIN_WIDTH( BUTTON_WIDTH*2), MAX_WIDTH( BUTTON_WIDTH*4)
{
	// set the dimensions of the sidebar (minimum width == BUTTON_WIDTH*2)
	int x( window.get_screen_width()/4);

	if( x < MIN_WIDTH)
		x = MIN_WIDTH;

	Toolbar::set_width( x);
	set_height( window.get_screen_height() - height - BORDER_WIDTH);

	// set the position of the sidebar (the top left is the anchor point)
	if( side == LEFT)
		set_x( 0);
	else
		set_x( window.get_screen_width()-get_width());
	set_y( height + BORDER_WIDTH);

	// work out the positioning of the buttons based on the current width of the sidebar
	update_button_positions();

	// the positioning of the background objects shouldn't be needed until they're rendered (i.e. they don't need to be saved)
}

//// DESTRUCTOR - ~Sidebar
Sidebar::~Sidebar() {
	p_ui_ = nullptr;
}
//-----------------

//-----------------
//// FUNCTION - get_button
// return the button number that's currently being cursored over
int Sidebar::get_button() const {
	// Pre-conditions :- the button number must be valid (if it isn't then this function shouldn't be called)
	assert( button_mouseover_ >= 0);

	return button_mouseover_;
}

//// FUNCTION - get_asset
// return the asset number that's currently being cursored over
int Sidebar::get_asset() const {
	// Pre-conditions :- the asset number must be valid (if it isn't then this function shouldn't be called)
	assert( asset_mouseover_ >= 0);

	return asset_mouseover_;
}

//// FUNCTION - get_active_button
// return the button that's currently active (i.e. whose list is being displayed)
int Sidebar::get_active_button() const {
	// Pre-conditions :- none
	assert( true);

	return button_active_;
}

//// FUNCTION - get_button_coordinates
// return the coordinates of the button
void Sidebar::get_button_coordinates( const int& b, int& x, int& y) const {
	// Pre-conditions :- button number must be valid
	assert( b <= 0 && b > BUTTON_ALL);

	x = buttons_[b][0];
	y = buttons_[b][1];
}

//// FUNCTION - mouseover_border
// return true if the mouse is currently over the sidebar
bool Sidebar::mouseover_border( const int& x, const int& y) const {
	// Pre-conditions :- none
	assert( true);

	int border_x( 0), border_y( get_y());

	if( alignment_ == LEFT)
		border_x = get_x() + get_width();
	else
		border_x = get_x() - BORDER_WIDTH;

	if( (x > border_x && x < border_x + BORDER_WIDTH) &&
		(y > border_y && y < border_y + get_height()))
		return true;
	else
		return false;
}

//// FUNCTION - get_asset_list_coordinates
// return the x and y coordinates where the asset list starts on the sidebar
void Sidebar::get_asset_list_coordinates( int& x, int& y) const {
	// Pre-conditions :- none
	assert( true);

	x = list_x_;
	y = list_y_;
}

//// FUNCTION - set_width
// set the width of the sidebar
void Sidebar::set_width( int x) {
	// Pre-conditions :- none

	if( x < MIN_WIDTH)
		x = MIN_WIDTH;
	else if( x > MAX_WIDTH)
		x = MAX_WIDTH;

	if( alignment_ == RIGHT)
		set_x( get_x() + get_width() - x);

	Toolbar::set_width( x);
	update_button_positions();
}

//// FUNCTION - mouseover_button
// return true if a button is being cursored over
bool Sidebar::mouseover_button( const int& x, const int& y) {
	// Pre-conditions :- none
	assert( true);

	// run through all the buttons in the array to test if they're under the mouse position
	for( int i( 0); i < BUTTON_ALL; i++) {
		if(( x >= buttons_[i][0] && x <= buttons_[i][0]+BUTTON_WIDTH) &&
		   ( y >= buttons_[i][1] && y <= buttons_[i][1]+BUTTON_HEIGHT) ) {
			button_mouseover_ = i;
			return true;
		}
	}

	// if none of the buttons are under the mouse then return false
	button_mouseover_ = -1;
	return false;
}

//// FUNCTION - set_active_button
// set the button that's currently being mouseovered to the active button
void Sidebar::set_active_button() {
	// Pre-conditions :- none
	assert( true);

	button_active_ = button_mouseover_;
}

//// FUNCTION - set_button_coordinates
// set the coordinates of the chosen button
void Sidebar::set_button_coordinates( const int& b, const int& x, const int& y) {
	// Pre-conditions :- none
	assert( true);

	// ensure the button number is valid before setting the position
	if( b < BUTTON_ALL) {
		buttons_[b][0] = x;
		buttons_[b][1] = y;
	}
}

//// FUNCTION - set_asset_mouseover
// set the asset number of the asset that is currently being cursored over
void Sidebar::set_asset_mouseover( const int& a) {
	// Pre-conditions :- none
	assert( true);

	asset_mouseover_ = a;
}

//// FUNCTION - setup_geometry
// create the meshes for the Sidebar
HRESULT Sidebar::setup_geometry( LPDIRECT3DDEVICE9 device) {
	// Pre-conditions :- the device must exist
	assert( device != nullptr);

	HRESULT hr;
	
	hr = Toolbar::setup_geometry( device);
	hr = hr | bg_lighter_.setup( device);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_bg_light.png").c_str(),					&bg_lighter_texture_);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_floor_passive.png").c_str(),		&buttons_textures_[BUTTON_FLOOR][BUTTON_TEXTURE_PASSIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_floor_mouseover.png").c_str(),		&buttons_textures_[BUTTON_FLOOR][BUTTON_TEXTURE_MOUSEOVER]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_floor_active.png").c_str(),			&buttons_textures_[BUTTON_FLOOR][BUTTON_TEXTURE_ACTIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_scenery_passive.png").c_str(),		&buttons_textures_[BUTTON_SCENERY][BUTTON_TEXTURE_PASSIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_scenery_mouseover.png").c_str(),	&buttons_textures_[BUTTON_SCENERY][BUTTON_TEXTURE_MOUSEOVER]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_scenery_active.png").c_str(),		&buttons_textures_[BUTTON_SCENERY][BUTTON_TEXTURE_ACTIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_doors_passive.png").c_str(),		&buttons_textures_[BUTTON_DOORS][BUTTON_TEXTURE_PASSIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_doors_mouseover.png").c_str(),		&buttons_textures_[BUTTON_DOORS][BUTTON_TEXTURE_MOUSEOVER]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_doors_active.png").c_str(),			&buttons_textures_[BUTTON_DOORS][BUTTON_TEXTURE_ACTIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_containers_passive.png").c_str(),	&buttons_textures_[BUTTON_CONTAINERS][BUTTON_TEXTURE_PASSIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_containers_mouseover.png").c_str(),	&buttons_textures_[BUTTON_CONTAINERS][BUTTON_TEXTURE_MOUSEOVER]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_containers_active.png").c_str(),	&buttons_textures_[BUTTON_CONTAINERS][BUTTON_TEXTURE_ACTIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_walls_passive.png").c_str(),		&buttons_textures_[BUTTON_WALLS][BUTTON_TEXTURE_PASSIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_walls_mouseover.png").c_str(),		&buttons_textures_[BUTTON_WALLS][BUTTON_TEXTURE_MOUSEOVER]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_walls_active.png").c_str(),			&buttons_textures_[BUTTON_WALLS][BUTTON_TEXTURE_ACTIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_waypoints_passive.png").c_str(),	&buttons_textures_[BUTTON_WAYPOINTS][BUTTON_TEXTURE_PASSIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_waypoints_mouseover.png").c_str(),	&buttons_textures_[BUTTON_WAYPOINTS][BUTTON_TEXTURE_MOUSEOVER]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_waypoints_active.png").c_str(),		&buttons_textures_[BUTTON_WAYPOINTS][BUTTON_TEXTURE_ACTIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_misc_passive.png").c_str(),			&buttons_textures_[BUTTON_MISC][BUTTON_TEXTURE_PASSIVE]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_misc_mouseover.png").c_str(),		&buttons_textures_[BUTTON_MISC][BUTTON_TEXTURE_MOUSEOVER]);
	hr = hr | D3DXCreateTextureFromFile( device, (PATH_ORTHOGRAPHIC+"texture_toolset_button_misc_active.png").c_str(),			&buttons_textures_[BUTTON_MISC][BUTTON_TEXTURE_ACTIVE]);

	return hr;
}

//// FUNCTION - render
// output the sidebar to the rendering device
void Sidebar::render( LPDIRECT3DDEVICE9 device, const Window& window) {
	// Pre-conditions :- the device must exist
	assert( device != nullptr);

	float x( 0), y( 0), sx( 0), sy( 0);

	// the background images need to be rendered first (i.e. the ones from Toolbar)
	// render the dark background of the sidebar
	x  = (get_x() + (get_width()/2)) / window.get_screen_width();
	y  = (window.get_screen_height() - get_y() - (get_height()/2)) / window.get_screen_height();
	sx = get_width() / window.get_screen_width();
	sy = get_height() / window.get_screen_height();
	orthographic_plane_.render( textures_[TEXTURE_BACKGROUND], x, y, 1.9, sx, sy, 1.0, 100);

	// render the lighter (inner) background of the sidebar
	x  = (get_x() + (get_width()/2)) / window.get_screen_width();
	y  = (window.get_screen_height() - (buttons_[BUTTON_ALL-1][1]+BUTTON_HEIGHT+5) - (((get_y() + get_height() - 5) - (buttons_[BUTTON_ALL-1][1]+BUTTON_HEIGHT+5)) /2)) / window.get_screen_height();
	sx = (get_width()-10) / window.get_screen_width();
	sy = ((get_y() + get_height() - 5) - (buttons_[BUTTON_ALL-1][1]+BUTTON_HEIGHT+5)) / window.get_screen_height();
	orthographic_plane_.render( bg_lighter_texture_, x, y, 1.8, sx, sy, 1.0, 100);

	// render the border
	if( alignment_ == LEFT)
		x = (get_x() + get_width() + (BORDER_WIDTH/2)) / window.get_screen_width();
	else
		x = (get_x() - (BORDER_WIDTH/2)) / window.get_screen_width();
	y  = (window.get_screen_height() - get_y() - (get_height()/2)) / window.get_screen_height();
	sx = float( BORDER_WIDTH) / window.get_screen_width();
	sy = get_height() / window.get_screen_height();
	orthographic_plane_.render( textures_[TEXTURE_BORDER], x, y, 1.7, sx, sy, 1.0, 100);

	// render the border's yellow hinges
	if( alignment_ == LEFT)
		x = (get_x() + get_width() + (BORDER_WIDTH/2)) / window.get_screen_width();
	else
		x = (get_x() - (BORDER_WIDTH/2)) / window.get_screen_width();
	y  = (window.get_screen_height() - get_y()) / window.get_screen_height();
	sx = float( BORDER_WIDTH) / window.get_screen_width();
	sy = float( BORDER_WIDTH) / window.get_screen_height();
	orthographic_plane_.render( textures_[TEXTURE_CORNER], x, y, 1.6, sx, sy, 1.0, 0.0, 0.0, 45.0, 100);

	// render the buttons
	for( int i( 0); i < BUTTON_ALL; i++) {
		LPDIRECT3DTEXTURE9* temp;

		x  = float( (buttons_[i][0] + (BUTTON_WIDTH/2))) / window.get_screen_width();
		y  = float( window.get_screen_height() - (buttons_[i][1] + (BUTTON_HEIGHT/2))) / window.get_screen_height();
		sx = float( BUTTON_WIDTH) / window.get_screen_width();
		sy = float( BUTTON_HEIGHT) / window.get_screen_height();

		// acquire the correct texture for the button and its current state
		if( i != button_active_ && i != button_mouseover_)
			temp = &buttons_textures_[i][BUTTON_TEXTURE_PASSIVE];
		else if( i == button_active_)
			temp = &buttons_textures_[i][BUTTON_TEXTURE_ACTIVE];
		else
			temp = &buttons_textures_[i][BUTTON_TEXTURE_MOUSEOVER];

		orthographic_plane_.render( *temp, x, y, 1.6, sx, sy, 1.0, 100);
	}
}

//// FUNCTION - reset
// clear all the user-created data in preparation of a new module
void Sidebar::reset() {
	// Pre-conditions :- none
	assert( true);

	button_mouseover_ = -1;
	asset_mouseover_ = -1;
}

//// FUNCTION - update_button_positions
// set the buttons to their new positions based on the width of the sidebar
void Sidebar::update_button_positions() {
	// Pre-conditions :- none
	assert( true);

	int x( get_width()), y( get_y()+5);  // y_+5 to leave a small gap
	int col1( 0), col2( 0), col3( 0), col4( 0);

	switch( int( get_width()) / BUTTON_WIDTH) {
		case 2:		// the minimum width of the sidebar is 2*BUTTON_WIDTH
			col1 = get_x() + x/2 - BUTTON_WIDTH;
			col2 = get_x() + x/2;

			for( int i( 0); i < BUTTON_ALL; i+=2, y+=BUTTON_HEIGHT) {
				set_button_coordinates( i  , col1, y);
				set_button_coordinates( i+1, col2, y);
			}
			break;
		case 3:
			col1 = get_x() + x/2 - (BUTTON_WIDTH + BUTTON_WIDTH/2);
			col2 = get_x() + x/2 - BUTTON_WIDTH/2;
			col3 = get_x() + x/2 + BUTTON_WIDTH/2;

			for( int i( 0); i < BUTTON_ALL; i+=3, y+=BUTTON_HEIGHT) {
				set_button_coordinates( i  , col1, y);
				set_button_coordinates( i+1, col2, y);
				set_button_coordinates( i+2, col3, y);
			}
			break;
		default:	// if it's greater than two or three buttons width then create four
			col1 = get_x() + x/2 - BUTTON_WIDTH*2;
			col2 = get_x() + x/2 - BUTTON_WIDTH;
			col3 = get_x() + x/2;
			col4 = get_x() + x/2 + BUTTON_WIDTH;

			for( int i( 0); i < BUTTON_ALL; i+=4, y+=BUTTON_HEIGHT) {
				set_button_coordinates( i  , col1, y);
				set_button_coordinates( i+1, col2, y);
				set_button_coordinates( i+2, col3, y);
				set_button_coordinates( i+3, col4, y);
			}
	}

	// work out where the list of assets starts
	list_x_ = get_x() + 10;
	list_y_ = buttons_[BUTTON_ALL-1][1] + CHAR_HEIGHT + 25;
}